feat(res-to-affine): Phase 3 slice 3 — literal let→const translation (Refs #57)#484
Merged
Merged
Conversation
…tion (Refs #57) Extends --translate to module-level value bindings: `let <id> = <literal>` becomes a typed AffineScript `const`, since AffineScript has no module-level `let` (a top-level value binding is `const name: Type = value;`). let answer = 42 -> const answer: Int = 42; let pi = 3.14 -> const pi: Float = 3.14; let greeting = "hi" -> const greeting: String = "hi"; let enabled = true -> const enabled: Bool = true; Conservative: only int/float/string/bool literals (type inferred, const type-checks standalone). A call body, a `ref(...)` mutable-global, a destructuring pattern, or an exotic number (hex/signed/scientific/underscored) is skipped — left as marker + quoted original, never a wrong const. Number forms limited to plain decimal int and D+.D+ float. Walker-internal (translate_literal / classify_number / translate_let_const + a let_declaration branch in collect_translations); Walker.translate / Emitter.emit_translation signatures unchanged. Scope boundary documented: switch->match (an expression needing whole-function translation of un-annotated ReScript fns) and qualified-path resolution stay out of the "every emitted form type-checks" scope. Verified locally with the apt-bootstrapped toolchain: full `dune build` exit 0; 22 res-to-affine walker tests green (4 new) against pinned grammar 990214a; `main.exe check` on the generated consts returns Type checking passed. Refs #57 https://claude.ai/code/session_017T8SzHr2yXav8hm4Ho76Uw
This was referenced May 31, 2026
8 tasks
🔍 Hypatia Security ScanFindings: 83 issues detected
View findings[
{
"reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action ons/checkout@v6\n needs attention",
"type": "unpinned_action",
"file": "publish-jsr.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action land/setup-deno@v2\n needs attention",
"type": "unpinned_action",
"file": "publish-jsr.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in affine-vscode-publish.yml",
"type": "missing_timeout_minutes",
"file": "affine-vscode-publish.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in casket-pages.yml",
"type": "missing_timeout_minutes",
"file": "casket-pages.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Third slice of Phase 3 for the
.res→.affinemigration assistant (#57). Extends--translateto module-level literalletbindings, lowering them to typed AffineScriptconstdeclarations (AffineScript has no module-levellet— a top-level value binding isconst name: Type = value;).let answer = 42const answer: Int = 42;let pi = 3.14const pi: Float = 3.14;let greeting = "hi"const greeting: String = "hi";let enabled = trueconst enabled: Bool = true;How / conservatism
Only int/float/string/bool literals translate — their type is inferred and the resulting
consttype-checks standalone (a literal is a compile-time constant). Skipped (left as marker + quoted original, never a wrong const):Date.now()), aref(...)(the mutable-global anti-pattern), etc.let (a, b) = …) — not a plain identifierD+.D+float, to avoid a literal the AffineScript lexer might reject)Walker-internal only (
classify_number/translate_literal/translate_let_const+ alet_declarationbranch incollect_translations);Walker.translate/Emitter.emit_translationsignatures unchanged.Scope boundary (the remaining #57 items)
The guarantee is "every emitted form type-checks standalone", which bounds translation to self-contained top-level declarations. Two forms are out of that scope by construction, now documented in the README:
switch→matchis an expression, only meaningful inside a function; a type-checkable result needs whole-function translation, but un-annotated ReScript fns (let f = x => …) can't yield a type-checkable AffineScriptfn(which needs param/return types). It belongs to a future partial-port mode that drops the standalone-type-check guarantee.Pkg.Type/Pkg.Effectunrepresentable (estate-wide port blocker; ADR-014) #228) but won't resolve without a module-mapping story.Verification (local, apt-bootstrapped toolchain)
dune builddune runtest tools/res-to-affine/990214amain.exe checkon the generated constsNo OCaml outside
tools/res-to-affine/walker.ml; config/compiler jobs unaffected.Refs #57https://claude.ai/code/session_017T8SzHr2yXav8hm4Ho76Uw
Generated by Claude Code